//-----------------------------------------------------------------------------
//
// @file	Vector.h
// @brief	Vector  classes (code modified from DonHouse, Texas A&M Univ)
// @author	Vinod Melapudi
// @date	20Feb2010
//
//-----------------------------------------------------------------------------

 
#ifndef _VECTOR_H
#define _VECTOR_H
 
#include "Utils.h" 
 
/* Vector Descriptions and Operations */ 

class Vector2; 
class Vector3; 
class Vector4; 
class Vector; 

class Vector2 { 
public: 
	float x, y; 

	Vector2(float vx = 0, float vy = 0); 
	Vector2(const Vector2 &v); 

	float& operator[](int i); 
	const float& operator[](int i) const; 

	operator Vector3(); 
	operator Vector4(); 
	operator Vector(); 

	void print() const; 
	void print(int w, int p) const;	// print with width and precision 

	float norm() const;			// magnitude of vector 
	float normsqr() const;		// magnitude squared 
	Vector2 normalize() const;		// normalize 

	void set(float vx = 0, float vy = 0);	// set assuming y = 0 
	void set(const Vector2 &v); 

	/* Vector2 operator prototypes */ 
	friend Vector2 operator-(const Vector2& v1); // unary negation of vector 
	friend Vector2 operator+(const Vector2& v1, const Vector2& v2);//addition  
	friend Vector2 operator-(const Vector2& v1, const Vector2& v2);//subtract 
	friend Vector2 operator*(const Vector2& v, float s); // scalar mult 
	friend Vector2 operator*(float s, const Vector2& v); 
	friend float   operator*(const Vector2& v1, const Vector2& v2); // dot 
	friend Vector2 operator^(const Vector2& v1, const Vector2& v2); //compt * 
	friend Vector3 operator%(const Vector2& v1, const Vector2& v2); // cross 
	friend Vector2 operator/(const Vector2& v, float s); // division by scalar 
	friend short    operator==(const Vector2& one, const Vector2& two); // eq 
}; 

class Vector3 { 
public: 
	float x, y, z; 

	Vector3(float vx = 0, float vy = 0, float vz = 0); 
	Vector3(const Vector3 &v); 
	Vector3(const Vector2 &v);

	float& operator[](int i); 
	const float& operator[](int i) const; 

	operator Vector4(); 
	operator Vector(); 

	void print() const; 
	void print(int w, int p) const;	// print with width and precision 

	float norm() const;			// magnitude of vector 
	float normsqr() const;		// magnitude squared 
	Vector3 normalize() const;		// normalize 

	void set(float vx = 0, float vy = 0, float vz = 0); // set 
	void set(const Vector3 &v); 

	/* Vector3 operator prototypes */ 
	friend Vector3 operator-(const Vector3& v1);	// unary negation 
	Vector3 operator+(const Vector3& v2) const;		// vector addition  
	void operator+=(const Vector3& v2);	// vector addition  
	friend Vector3 operator-(const Vector3& v1, const Vector3& v2); // subtract 
	void operator-=(const Vector3& v2);	// vector subtract  
	friend Vector3 operator*(const Vector3& v, float s);      // multiply 
	friend Vector3 operator*(float s, const Vector3& v); 
	friend float   operator*(const Vector3& v1, const Vector3& v2); // dot 
	friend Vector3 operator^(const Vector3& v1, const Vector3& v2); // compt * 
	friend Vector3 operator%(const Vector3& v1, const Vector3& v2); // cross 
	friend Vector3 operator/(const Vector3& v, float s); // division by scalar 
	friend short    operator==(const Vector3& one, const Vector3& two); // equ 
}; 

class Vector4 { 
public: 
	float x, y, z, w; 

	Vector4(float vx = 0, float vy = 0, float vz = 0, float vw = 0); 
	Vector4(const Vector4 &v);
	Vector4(const Vector3 &v);

	float& operator[](int i); 
	const float& operator[](int i) const; 

	operator Vector(); 

	void print() const; 
	void print(int w, int p) const;	// print with width and precision 

	float norm() const;			// magnitude of vector 
	float normsqr() const;		// magnitude squared 
	Vector4 normalize() const;		// normalize 
	Vector4 wnorm() const;		// normalize to w coord. 

	void set(float vx = 0, float vy = 0, float vz = 0, float vw = 0); // set 
	void set(const Vector4 &v); 

	/* Vector4 operator prototypes */ 
	friend Vector4 operator-(const Vector4& v1);  // unary negation 
	Vector4 operator+(const Vector4& v2) const; // vector addition  
	friend Vector4 operator-(const Vector4& v1, const Vector4& v2); //subtract 
	friend Vector4 operator*(const Vector4& v, float s);	// multiply 
	friend Vector4 operator*(float s, const Vector4& v); 
	friend float   operator*(const Vector4& v1, const Vector4& v2); // dot 
	friend Vector4 operator^(const Vector4& v1, const Vector4& v2); // compt * 
	friend Vector4 operator%(const Vector4& v1, const Vector4& v2); // cross 
	friend Vector4 operator/(const Vector4& v, float s); // divide by scalar 
	friend short    operator==(const Vector4& one, const Vector4& two); // equ 
}; 

class Vector { 
protected: 
	int N; 
	float *v; 

public: 
	Vector(int vN = 0, float *vx = NULL); 
	Vector(const Vector& V); 
	Vector(float vx, float vy); 
	Vector(float vx, float vy, float vz); 
	Vector(float vx, float vy, float vz, float vw); 

	~Vector(); 

	void setsize(int vN); 

	float& operator[](int i); 
	const float& operator[](int i) const;   

	operator Vector2(); 
	operator Vector3(); 
	operator Vector4(); 

	int getn() const; 

	void print() const; 
	void print(int w, int p) const;	// print with width and precision 

	float norm() const;			// magnitude of vector 
	float normsqr() const;		// magnitude squared 
	Vector normalize() const;		// normalize 

	void set(float *vx); 		// set 
	void set(const Vector &v); 
	void set(float vx, float vy); 
	void set(float vx, float vy, float vz); 
	void set(float vx, float vy, float vz, float vw);   

	/* Vector operator prototypes */ 
	const Vector& operator=(const Vector& v2);		// assignment 
	friend Vector operator-(const Vector& v1);		// unary negation 
	friend Vector operator+(const Vector& v1, const Vector& v2); // vector add 
	friend Vector operator-(const Vector& v1, const Vector& v2); // vector sub 
	friend Vector operator*(const Vector& v, float s);       // scalar multiply 
	friend Vector operator*(float s, const Vector& v); 
	friend Vector operator^(const Vector& v1, const Vector& v2); // component * 
	friend float operator*(const Vector& v1, const Vector& v2); // dot product  
	friend Vector operator%(const Vector& v1, const Vector& v2); // cross product 
	friend Vector operator/(const Vector& v, float s);	  // division by scalar 
	friend short  operator==(const Vector& one, const Vector& two); // equality 
}; 
 
#endif 
